import { getSession } from '@/lib/auth';
import { db } from '@/lib/db';
import { product, shop } from '@/lib/db/schema/common';
import { result } from '@/lib/utils';
import { and, between, eq, ilike, inArray } from 'drizzle-orm';
import { BizError, ErrorCode } from '../error';
import type { Pagination } from '../type/pagination';

export const listProductsByPage = async (args: {
  page: number;
  pageSize: number;
  id?: number;
  name?: string;
  description?: string;
  price?: string;
  createdDateRange?: {
    from: Date;
    to?: Date;
  };
  updatedDateRange?: {
    from: Date;
    to?: Date;
  };
}) => {
  try {
    const session = await getSession();
    if (!session?.user)
      throw new BizError(ErrorCode.Unauthorized, '用户未登录');
    const res = await db
      .select({
        id: product.id,
        name: product.name,
        price: product.price,
        description: product.description,
        imageKeys: product.imageKeys,
        createdAt: product.createdAt,
        updatedAt: product.updatedAt,
      })
      .from(product)
      .innerJoin(shop, eq(shop.id, product.shopId))
      .where(
        and(
          eq(shop.userId, session.user.id),
          args.id !== undefined ? eq(product.id, args.id) : undefined,
          args.name !== undefined
            ? ilike(product.name, `%${args.name}%`)
            : undefined,
          args.description !== undefined
            ? ilike(product.description, `%${args.description}%`)
            : undefined,
          args.price !== undefined ? eq(product.price, args.price) : undefined,
          args.createdDateRange !== undefined
            ? between(
                product.createdAt,
                args.createdDateRange.from,
                args.createdDateRange.to
                  ? args.createdDateRange.to
                  : new Date(),
              )
            : undefined,
          args.updatedDateRange !== undefined
            ? between(
                product.updatedAt,
                args.updatedDateRange.from,
                args.updatedDateRange.to
                  ? args.updatedDateRange.to
                  : new Date(),
              )
            : undefined,
        ),
      )
      .orderBy(product.createdAt)
      .limit(args.pageSize + 1)
      .offset((args.page - 1) * args.pageSize);
    if (res.length > args.pageSize) {
      res.pop();
      return result({
        data: res,
        next: args.page + 1,
      } satisfies Pagination<(typeof res)[0]>);
    }
    return result({ data: res, next: null } satisfies Pagination<
      (typeof res)[0]
    >);
  } catch (error) {
    return result(error, '获取外卖失败');
  }
};

export const getProduct = async (id: number) => {
  try {
    const session = await getSession();
    if (!session?.user)
      throw new BizError(ErrorCode.Unauthorized, '用户未登录');
    const res = await db
      .select({
        id: product.id,
        shopId: product.shopId,
        name: product.name,
        price: product.price,
        description: product.description,
        imageKeys: product.imageKeys,
        createdAt: product.createdAt,
        updatedAt: product.updatedAt,
      })
      .from(product)
      .innerJoin(shop, eq(shop.id, product.shopId))
      .where(and(eq(shop.userId, session.user.id), eq(product.id, id)))
      .limit(1);
    if (!res) throw new BizError(ErrorCode.NotFound, '外卖不存在');
    return result(res[0]);
  } catch (error) {
    return result(error, '获取外卖失败');
  }
};

export const getProductById = async (id: number) => {
  try {
    const res = await db.query.product.findFirst({
      where: (product, { eq }) => eq(product.id, id),
      with: {
        shop: true,
      },
    });
    if (!res) throw new BizError(ErrorCode.NotFound, '外卖不存在');
    return result(res);
  } catch (error) {
    return result(error, '获取外卖失败');
  }
};

export const getProductsByIds = async (ids: number[]) => {
  try {
    const res = await db.query.product.findMany({
      where: (product, { inArray }) => inArray(product.id, ids),
    });
    return result(res);
  } catch (error) {
    return result(error, '获取外卖失败');
  }
};
